/*==============================================================================
 * AUTH: Matthew Baum, 9753095
 * DATE: February-15-2012
 * EDIT: March-04-2012
 * DESC: Represents the UI/Swing Components for the TaskPro system.
 *==============================================================================*/

package SOEN_Phase_2;

// Import SWING GUI libraries
// General window
import javax.swing.JFrame;

import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;

// Menu items/menu bar
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

// General window events
import java.awt.event.WindowListener;
import java.awt.event.WindowEvent;

// Scrolling pane
import javax.swing.JScrollPane;

// Table display
import javax.swing.JTable;

// Text & Button display
import javax.swing.JLabel;
import javax.swing.JButton;

// Event handling
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;

// File chooser
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileFilter;

// Security libraries
import java.security.PrivilegedAction;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;


// Main GUI Class
public class TaskProUI extends JFrame implements WindowListener, CellEditorListener
{
        //File filter for the save dialog box
        class TextFilter extends FileFilter {
        @Override
        public boolean accept(File file) {
            // Allow only directories, or files with ".txt" extension
            return file.isDirectory() || file.getAbsolutePath().endsWith(".txt");
        }
        @Override
        public String getDescription() {
            // This description will be displayed in the dialog
            return "Text documents (*.txt)";
        }
    } 

    // A reference to the "owner" TaskPro instance
    private TaskPro owner = null;

    // GUI Tables
    private JTable tTbl, pTbl;

    // Static helper to add a menu bar to a new GUI instance
    private void addMenuBar()
    {
        // Create the menu bar.
        JMenuBar menuBar = new JMenuBar();
        JMenuItem menuItem;

        // Build the first menu.
        JMenu menu;

        // Set the menu
        menu = new JMenu("File");
        menu.getAccessibleContext().setAccessibleDescription("File dialogs");
        menuBar.add(menu);

        // Set first menu item: save task table to TXT
        menuItem = new JMenuItem("Save Task Table to TXT");
        menuItem.addActionListener(new SaveDialog(true) );
        menu.add(menuItem);

        // Set second menu item
        menuItem = new JMenuItem("Save Person Table to TXT");
        menuItem.addActionListener(new SaveDialog(false) );
        menu.add(menuItem);
        
        // Set exit menu item
        menuItem = new JMenuItem("Exit");

        menuItem.addActionListener
        (
            new ActionListener()
            {
                public void actionPerformed(ActionEvent e)
                {
                    owner.saveAndClose();
                }
            }
        );
        
        menuItem.setMnemonic('x');
        menu.add(menuItem);

        // Set "Edit" menu
        menu = new JMenu("Edit");
        menu.getAccessibleContext().setAccessibleDescription("Edit data");
        menuBar.add(menu);

        // Set first menu item: Create new task
        menuItem = new JMenuItem("New Task...");
        menuItem.addActionListener(new TaskCreationDialog(owner.getTaskTable(),
                owner.getPersonTable()) );
        menu.add(menuItem);

        // Set second menu item: Delete Task
        menuItem = new JMenuItem("Delete Task...");
        menuItem.addActionListener(new TaskDeletionDialog(owner.getTaskTable(), owner.getPersonTable()));
        menu.add(menuItem);

        // Set the menu bar on the GUI item
        setJMenuBar(menuBar);
    }

    // Helpers to add tables to a new GUI instance
    private void addTaskTable(GridBagConstraints c)
    {
        tTbl = new JTable(owner.getTaskTable());
        JScrollPane p = new JScrollPane(tTbl);
        tTbl.getDefaultEditor(String.class).addCellEditorListener(this);
        tTbl.getDefaultEditor(Integer.class).addCellEditorListener(this);
        tTbl.getDefaultEditor(Boolean.class).addCellEditorListener(this);
        this.add(p,c);
    }

    private void addPersonTable(GridBagConstraints c)
    {
        pTbl = new JTable(owner.getPersonTable());
        JScrollPane p = new JScrollPane(pTbl);
        this.add(p,c);
    }

    // Constructor
    public TaskProUI(TaskPro own)
    {
        // Set "owner" TaskPro object
        owner = own;

        // Set window title
        super.setTitle("TaskPro");

        // Set window size
        super.setSize(900, 600);

        // Add a menu bar to the UI
        addMenuBar();

        // Add frames to the UI
        GridBagLayout gridbag = new GridBagLayout();
            GridBagConstraints c  = new GridBagConstraints();
        setLayout(gridbag);
        
        c.fill = GridBagConstraints.BOTH;
        c.gridwidth = 2;
        c.weightx = 0.; c.weighty = 0.;
                
                // Add labels
                c.gridy = 0;
                add(new JLabel("Tasks"),c);
                add(new JLabel("Employees"),c);         
                
        // Add Tables
        c.weightx = 1.; c.weighty = 1.;
        c.gridy = 1;
        addTaskTable(c);                                // Tasks
        addPersonTable(c);              // People

            c.gridwidth = 1;
        c.gridy = 2;
        c.weightx = 1.; c.weighty = 0.;
        JButton b;
        b = new JButton("New");         // New Task
        add(b,c);
        b.addActionListener(new TaskCreationDialog(owner.getTaskTable(),
                owner.getPersonTable()) );

        b = new JButton("Delete");      // Delete Task
        b.addActionListener( new TaskDeletionDialog(owner.getTaskTable(),
                owner.getPersonTable()));
        add(b,c);

        // Set window to visible
        setVisible(true);

        // Set Default Exit action
        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);

        // Set the new UI object as its own window event listener
        // WARNING: Leaking "yhis" in constructor!
        addWindowListener(this);
    }
    
    @Override
    public void editingStopped(ChangeEvent e)
    {
        // Update table when a change is detected
        owner.updateTable();
        
        owner.getPersonTable().writeToXML(owner.getPersonXMLPath());
        owner.getTaskTable().saveToXML(owner.getTaskXMLPath());
        
        owner.getTaskTable().fireTableDataChanged();
        owner.getPersonTable().fireTableDataChanged();
    }
    
    @Override
    public void editingCanceled(ChangeEvent e)
    {
        // Do Nothing
        System.out.println("Editing cancelled");
    }

    /*==========================================================
     * INNER CLASS:
     * Event handler used to save tables to text files.
     *==========================================================*/
    private class SaveDialog implements ActionListener, PrivilegedAction
    {
        // Boolean flag used to determine the table being saved
        private boolean isTaskTable;

        // Constructor
        public SaveDialog(boolean isTask)
        {
            isTaskTable = isTask;
        }

        // Event handling routine
        @Override
        public void actionPerformed(ActionEvent e)
        {
            // Run Save dialog as a privileged action for security
            run();
        }

        // Wrap save dialog in a privileged action
        @Override
        public Object run()
        {
            // Create a file chooser: empty string fixes error on some platforms
            JFileChooser fileChooser = new JFileChooser("");
            fileChooser.addChoosableFileFilter(new TextFilter());

            // Strings to hold directory and file names
            String dirName = null, fName = null;

            // Create a save dialog, using the TaskProUI object
            int statusCode = fileChooser.showSaveDialog(TaskProUI.this);

            // IF user clicked APPROVE
            if (statusCode == JFileChooser.APPROVE_OPTION)
            {
                dirName = fileChooser.getCurrentDirectory().toString();
                File selected = fileChooser.getSelectedFile();
                
                //append .txt to file name - that way, it's saved as .txt automatically
                fName = selected.getName();
                if (fName.indexOf('.')==-1) 
                {
                        fName += ".txt";
                        selected = new File(selected.getParentFile(), fName);
                }
            }

            // IF task dialog: Save the table to TXT
            if(isTaskTable && dirName != null && fName != null)
            {
                owner.writeTaskTableToTXT(dirName, fName);
            }

            // ELSE
            else if(dirName != null && fName != null)
            {
                owner.writePersonTableToTXT(dirName, fName);
            }

            // Nothing in particular to return for now
            return null;
        }
    }

    // ABSTRACT IMPLEMENTATION from WindowListener
    // ON CLOSE: save data, then quit
    @Override
    public void windowClosing(WindowEvent e)
    {
        // Call Save-and-Close on owner
        owner.saveAndClose();

        // Dispose this UI window
        this.dispose();
    }

    // ABSTRACT IMPLEMENTATION from WindowListener
    @Override
    public void windowActivated(WindowEvent e)
    {
        // Do nothing!
    }

    // ABSTRACT IMPLEMENTATION from WindowListener
    @Override
    public void windowDeactivated(WindowEvent e)
    {
        // Do nothing!
    }

    // ABSTRACT IMPLEMENTATION from WindowListener
    @Override
    public void windowIconified(WindowEvent e)
    {
        // Do nothing!
    }

    // ABSTRACT IMPLEMENTATION from WindowListener
    @Override
    public void windowDeiconified(WindowEvent e)
    {
        // Do nothing!
    }

    // ABSTRACT IMPLEMENTATION from WindowListener
    @Override
    public void windowClosed(WindowEvent e)
    {
        // Do nothing!
    }

    // ABSTRACT IMPLEMENTATION from WindowListener
    @Override
    public void windowOpened(WindowEvent e)
    {
        // Do nothing!
    }
}
